package com.fx.controller;

import com.fx.common.ActionControllerHandlerBuilder;
import com.fx.common.MenuItemActionType;
import com.fx.common.MenuItemController;
import com.fx.common.RootStage;
import com.fx.common.impl.ApplicationControlActionController;
import com.fx.view.CreateNewProjectView;
import com.fx.view.ProjectWindowView;
import de.felixroske.jfxsupport.FXMLController;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.RadioMenuItem;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;

import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.ResourceBundle;

/**
 * 参考：https://blog.csdn.net/qq_31384551/article/details/81238048
 */
@Slf4j
@FXMLController
public class MainStageController implements Initializable {

    @FXML
    private VBox mainVBox; //为其id

    @FXML
    private MenuBar mainMenuBar;

    @FXML
    private MenuItem menuOpen;

    @FXML
    private MenuItem newProjectItem;

    @Autowired
    private ProjectWindowView projectWindowView;

    @Autowired
    private ActionControllerHandlerBuilder actionControllerHandlerBuilder;

    private final KeyCombination.Modifier modifier = KeyCombination.CONTROL_DOWN;
    private final Map<KeyCombination,MenuItem> keyToMenu = new HashMap<>();

    private final EventHandler<ActionEvent> onActionEventHandler = t -> {
      assert t.getSource() instanceof MenuItem;
      handleOnActionMenu((MenuItem) t.getSource());
    };

    private void handleOnActionMenu(MenuItem item){
        if(item.getUserData() == null){
            return;
        }
        assert item.getUserData() instanceof MenuItemController;
        final MenuItemController controller = (MenuItemController) item.getUserData();
        controller.perform();
    }

    private final EventHandler<Event> onMenuValidationEventHandler = t -> {
      assert t.getSource() instanceof Menu;
      handleOnMenuValidation((Menu) t.getSource());
    };

    private void handleOnMenuValidation(Menu menu) {
        for (MenuItem i : menu.getItems()) {
            final boolean disable, selected;
            final String title;
            if(i.getUserData() == null){
                return;
            }
            if (i.getUserData() instanceof MenuItemController) {
                final MenuItemController c = (MenuItemController) i.getUserData();
                boolean canPerform;
                try {
                    canPerform = c.canPerform();
                } catch(RuntimeException x) {
                    // This catch is protection against a bug in canPerform().
                    // It avoids to block all the items in the menu in case
                    // of crash in canPerform() (see DTL-6164).
                    canPerform = false;
                    final Exception xx
                            = new Exception(c.getClass().getSimpleName()
                            + ".canPerform() did break for menu item " + i, x); //NOI18N
                    xx.printStackTrace();
                }
                disable = !canPerform;
                title = c.getTitle();
                selected = c.isSelected();
            } else {
                if (i instanceof Menu) {
                    disable = false;
                    selected = false;
                    title = null;
                } else {
                    disable = true;
                    selected = false;
                    title = null;
                }
            }
            i.setDisable(disable);
            if (title != null) {
                i.setText(title);
            }
            if (i instanceof RadioMenuItem) {
                final RadioMenuItem ri = (RadioMenuItem) i;
                ri.setSelected(selected);
            }
        }
    }

    private void setupMenuItemHandlers(MenuItem item){
        if(item instanceof Menu){
            final Menu m = (Menu) item;
            m.setOnMenuValidation(onMenuValidationEventHandler);
            for(MenuItem child : m.getItems()){
                setupMenuItemHandlers(child);
            }
        }else{
            item.setOnAction(onActionEventHandler);
            if(item.getAccelerator() != null){
                keyToMenu.put(item.getAccelerator(),item);
            }
        }
    }


    private void initMenuActionEventHandlers(){
        newProjectItem.setUserData(new
                ApplicationControlActionController(MenuItemActionType.NEW_PROJECT,actionControllerHandlerBuilder));
        // 添加userData
        for(Menu m : mainMenuBar.getMenus()){
            setupMenuItemHandlers(m);
        }
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        mainMenuBar.prefWidthProperty().bind(mainVBox.widthProperty());
        mainVBox.getChildren().add(projectWindowView.getView());
        initMenuItem();
        initMenuActionEventHandlers();
    }

    private void initMenuItem(){
       addImage(menuOpen,"images/kooteam.ico","Shit+T");
    }

    private void addImage(MenuItem item,String imagePath,String keyInfo){

        if(StringUtils.isNotBlank(imagePath)){
            ClassPathResource r = new ClassPathResource(imagePath);
            try {
                item.setGraphic(new ImageView(new Image(r.getInputStream())));
            } catch (IOException e) {
                log.error("获取图片异常",e);
            }
        }
        if(StringUtils.isNotBlank(keyInfo)){
            item.setAccelerator(new KeyCodeCombination(KeyCode.N,modifier));
        }
    }

}
